home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / Misc / Mapper / MapperDlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  26.5 KB  |  868 lines

  1. //------------------------------------------------------------------------------
  2. // File: MapperDlg.cpp
  3. //
  4. // Desc: DirectShow sample code - an MFC based C++ filter mapper application.
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8. // MapperDlg.cpp : implementation file
  9. //
  10.  
  11. #include "stdafx.h"
  12. #include "Mapper.h"
  13. #include "MapperDlg.h"
  14.  
  15. #include "types.h"
  16. #include "wxdebug.h"
  17. #include "fil_data.h"
  18.  
  19. #ifdef _DEBUG
  20. #define new DEBUG_NEW
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24.  
  25. // ID for unpublished filter data helper method
  26. const IID IID_IAMFilterData = {0x97f7c4d4,0x547b,0x4a5f,{0x83,0x32,0x53,0x64,0x30,0xad,0x2e,0x4d}};
  27.  
  28.  
  29. /////////////////////////////////////////////////////////////////////////////
  30. // CAboutDlg dialog used for App About
  31.  
  32. class CAboutDlg : public CDialog
  33. {
  34. public:
  35.     CAboutDlg();
  36.  
  37. // Dialog Data
  38.     //{{AFX_DATA(CAboutDlg)
  39.     enum { IDD = IDD_ABOUTBOX };
  40.     //}}AFX_DATA
  41.  
  42.     // ClassWizard generated virtual function overrides
  43.     //{{AFX_VIRTUAL(CAboutDlg)
  44.     protected:
  45.     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  46.     //}}AFX_VIRTUAL
  47.  
  48. // Implementation
  49. protected:
  50.     //{{AFX_MSG(CAboutDlg)
  51.     //}}AFX_MSG
  52.     DECLARE_MESSAGE_MAP()
  53. };
  54.  
  55. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  56. {
  57.     //{{AFX_DATA_INIT(CAboutDlg)
  58.     //}}AFX_DATA_INIT
  59. }
  60.  
  61. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  62. {
  63.     CDialog::DoDataExchange(pDX);
  64.     //{{AFX_DATA_MAP(CAboutDlg)
  65.     //}}AFX_DATA_MAP
  66. }
  67.  
  68. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  69.     //{{AFX_MSG_MAP(CAboutDlg)
  70.         // No message handlers
  71.     //}}AFX_MSG_MAP
  72. END_MESSAGE_MAP()
  73.  
  74. /////////////////////////////////////////////////////////////////////////////
  75. // CMapperDlg dialog
  76.  
  77. CMapperDlg::CMapperDlg(CWnd* pParent /*=NULL*/)
  78.     : CDialog(CMapperDlg::IDD, pParent)
  79. {
  80.     //{{AFX_DATA_INIT(CMapperDlg)
  81.     //}}AFX_DATA_INIT
  82.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  83.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  84. }
  85.  
  86. void CMapperDlg::DoDataExchange(CDataExchange* pDX)
  87. {
  88.     CDialog::DoDataExchange(pDX);
  89.     //{{AFX_DATA_MAP(CMapperDlg)
  90.     DDX_Control(pDX, IDC_BUTTON_SEARCH, m_bSearch);
  91.     DDX_Control(pDX, IDC_BUTTON_CLEAR, m_bClear);
  92.     DDX_Control(pDX, IDC_STATIC_NUMFILTERS, m_StrNumFilters);
  93.     DDX_Control(pDX, IDC_CHECK_RENDERER, m_bIsRenderer);
  94.     DDX_Control(pDX, IDC_CHECK_OUTPUT_PIN, m_bAtLeastOneOutputPin);
  95.     DDX_Control(pDX, IDC_CHECK_INPUT_PIN, m_bAtLeastOneInputPin);
  96.     DDX_Control(pDX, IDC_CHECK_EXACT_MATCH, m_bExactMatch);
  97.     DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR2, m_ListOutputMinor2);
  98.     DDX_Control(pDX, IDC_LIST_OUTPUT_MINOR, m_ListOutputMinor);
  99.     DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR2, m_ListOutputMajor2);
  100.     DDX_Control(pDX, IDC_LIST_OUTPUT_MAJOR, m_ListOutputMajor);
  101.     DDX_Control(pDX, IDC_LIST_INPUT_MINOR2, m_ListInputMinor2);
  102.     DDX_Control(pDX, IDC_LIST_INPUT_MINOR, m_ListInputMinor);
  103.     DDX_Control(pDX, IDC_LIST_INPUT_MAJOR2, m_ListInputMajor2);
  104.     DDX_Control(pDX, IDC_LIST_INPUT_MAJOR, m_ListInputMajor);
  105.     DDX_Control(pDX, IDC_COMBO_MERIT, m_ComboMerit);
  106.     DDX_Control(pDX, IDC_COMBO_OUTPUT_CATEGORY, m_ComboOutputCat);
  107.     DDX_Control(pDX, IDC_COMBO_INPUT_CATEGORY, m_ComboInputCat);
  108.     DDX_Control(pDX, IDC_LIST_FILTERS, m_ListFilters);
  109.     //}}AFX_DATA_MAP
  110. }
  111.  
  112. BEGIN_MESSAGE_MAP(CMapperDlg, CDialog)
  113.     //{{AFX_MSG_MAP(CMapperDlg)
  114.     ON_WM_SYSCOMMAND()
  115.     ON_WM_PAINT()
  116.     ON_WM_QUERYDRAGICON()
  117.     ON_WM_CLOSE()
  118.     ON_WM_DESTROY()
  119.     ON_BN_CLICKED(IDC_BUTTON_SEARCH, OnButtonSearch)
  120.     ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR, OnSelchangeListInputMajor)
  121.     ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR, OnSelchangeListOutputMajor)
  122.     ON_LBN_SELCHANGE(IDC_LIST_INPUT_MAJOR2, OnSelchangeListInputMajor2)
  123.     ON_LBN_SELCHANGE(IDC_LIST_OUTPUT_MAJOR2, OnSelchangeListOutputMajor2)
  124.     ON_BN_CLICKED(IDC_BUTTON_CLEAR, OnButtonClear)
  125.     //}}AFX_MSG_MAP
  126. END_MESSAGE_MAP()
  127.  
  128. /////////////////////////////////////////////////////////////////////////////
  129. // CMapperDlg message handlers
  130.  
  131. void CMapperDlg::OnSysCommand(UINT nID, LPARAM lParam)
  132. {
  133.     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  134.     {
  135.         CAboutDlg dlgAbout;
  136.         dlgAbout.DoModal();
  137.     }
  138.     else
  139.     {
  140.         CDialog::OnSysCommand(nID, lParam);
  141.     }
  142. }
  143.  
  144. // If you add a minimize button to your dialog, you will need the code below
  145. //  to draw the icon.  For MFC applications using the document/view model,
  146. //  this is automatically done for you by the framework.
  147.  
  148. void CMapperDlg::OnPaint() 
  149. {
  150.     if (IsIconic())
  151.     {
  152.         CPaintDC dc(this); // device context for painting
  153.  
  154.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  155.  
  156.         // Center icon in client rectangle
  157.         int cxIcon = GetSystemMetrics(SM_CXICON);
  158.         int cyIcon = GetSystemMetrics(SM_CYICON);
  159.         CRect rect;
  160.         GetClientRect(&rect);
  161.         int x = (rect.Width() - cxIcon + 1) / 2;
  162.         int y = (rect.Height() - cyIcon + 1) / 2;
  163.  
  164.         // Draw the icon
  165.         dc.DrawIcon(x, y, m_hIcon);
  166.     }
  167.     else
  168.     {
  169.         CDialog::OnPaint();
  170.     }
  171. }
  172.  
  173. // The system calls this to obtain the cursor to display while the user drags
  174. //  the minimized window.
  175. HCURSOR CMapperDlg::OnQueryDragIcon()
  176. {
  177.     return (HCURSOR) m_hIcon;
  178. }
  179.  
  180.  
  181. BOOL CMapperDlg::OnInitDialog()
  182. {
  183.     CDialog::OnInitDialog();
  184.  
  185.     // Add "About..." menu item to system menu.
  186.  
  187.     // IDM_ABOUTBOX must be in the system command range.
  188.     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  189.     ASSERT(IDM_ABOUTBOX < 0xF000);
  190.  
  191.     CMenu* pSysMenu = GetSystemMenu(FALSE);
  192.     if (pSysMenu != NULL)
  193.     {
  194.         CString strAboutMenu;
  195.         strAboutMenu.LoadString(IDS_ABOUTBOX);
  196.         if (!strAboutMenu.IsEmpty())
  197.         {
  198.             pSysMenu->AppendMenu(MF_SEPARATOR);
  199.             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  200.         }
  201.     }
  202.  
  203.     // Set the icon for this dialog.  The framework does this automatically
  204.     //  when the application's main window is not a dialog
  205.     SetIcon(m_hIcon, TRUE);            // Set big icon
  206.     SetIcon(m_hIcon, FALSE);        // Set small icon
  207.     
  208.  
  209.     //////////////////////////////////////////////////////////////////////////
  210.     //
  211.     // DirectShow initialization code
  212.  
  213.     CoInitialize(NULL);
  214.  
  215.     // Create the filter mapper that will be used for all queries    
  216.     HRESULT hr = CoCreateInstance(CLSID_FilterMapper2, 
  217.                           NULL, CLSCTX_INPROC, IID_IFilterMapper2, 
  218.                           (void **) &m_pMapper);
  219.     ASSERT(SUCCEEDED(hr));
  220.     if (FAILED(hr))
  221.         return FALSE;
  222.  
  223.     // Initialize some application settings
  224.     InitializeTooltips();
  225.     SetDefaults();
  226.  
  227.     // Customize list box tab stops for good formatting
  228.     int nTabStops[2]={140,230};
  229.     m_ListFilters.SetTabStops(2, nTabStops);
  230.  
  231.     return TRUE;  // return TRUE  unless you set the focus to a control
  232. }
  233.  
  234. BOOL CMapperDlg::InitializeTooltips()
  235. {
  236.     int rc;
  237.  
  238.     // Create the tooltip control
  239.     m_pToolTip = new CToolTipCtrl;
  240.     if(!m_pToolTip->Create(this))
  241.     {
  242.        TRACE(TEXT("Unable To create ToolTip\n"));
  243.        return FALSE;
  244.     }
  245.  
  246.     // Set some tooltip defaults
  247.     m_pToolTip->SetMaxTipWidth(250);
  248.     m_pToolTip->SetDelayTime(TTDT_AUTOPOP, 10000);  /* 10s  */
  249.     m_pToolTip->SetDelayTime(TTDT_INITIAL, 2000);   /* 2s */
  250.  
  251.     // Add tooltip strings for the relevant controls
  252.     rc = m_pToolTip->AddTool(&m_bExactMatch,          TTSTR_EXACT_MATCH);
  253.     rc = m_pToolTip->AddTool(&m_bAtLeastOneInputPin,  TTSTR_ALOIP);
  254.     rc = m_pToolTip->AddTool(&m_bAtLeastOneOutputPin, TTSTR_ALOOP);
  255.     rc = m_pToolTip->AddTool(&m_bIsRenderer,          TTSTR_IS_RENDERER);
  256.     rc = m_pToolTip->AddTool(&m_bClear,               TTSTR_CLEAR);
  257.     rc = m_pToolTip->AddTool(&m_bSearch,              TTSTR_SEARCH);
  258.     rc = m_pToolTip->AddTool(&m_ListFilters,          TTSTR_FILTERS);
  259.     rc = m_pToolTip->AddTool(&m_ComboMerit,           TTSTR_MERIT);
  260.     rc = m_pToolTip->AddTool(&m_ComboInputCat,        TTSTR_PIN_CAT);
  261.     rc = m_pToolTip->AddTool(&m_ComboOutputCat,       TTSTR_PIN_CAT);
  262.     rc = m_pToolTip->AddTool(&m_ListInputMajor,       TTSTR_TYPE);
  263.     rc = m_pToolTip->AddTool(&m_ListInputMajor2,      TTSTR_TYPE);
  264.     rc = m_pToolTip->AddTool(&m_ListOutputMajor,      TTSTR_TYPE);
  265.     rc = m_pToolTip->AddTool(&m_ListOutputMajor2,     TTSTR_TYPE);
  266.     rc = m_pToolTip->AddTool(&m_ListInputMinor,       TTSTR_SUBTYPE);
  267.     rc = m_pToolTip->AddTool(&m_ListInputMinor2,      TTSTR_SUBTYPE);
  268.     rc = m_pToolTip->AddTool(&m_ListOutputMinor,      TTSTR_SUBTYPE);
  269.     rc = m_pToolTip->AddTool(&m_ListOutputMinor2,     TTSTR_SUBTYPE);
  270.  
  271.     // Activate the tooltip control
  272.     m_pToolTip->Activate(TRUE);
  273.     return TRUE;
  274. }
  275.  
  276. BOOL CMapperDlg::PreTranslateMessage(MSG* pMsg) 
  277. {
  278.     // Let the tooltip process the message, if appropriate
  279.     if (m_pToolTip)
  280.         m_pToolTip->RelayEvent(pMsg);
  281.     
  282.     return CDialog::PreTranslateMessage(pMsg);
  283. }
  284.  
  285. void CMapperDlg::SetDefaults()
  286. {
  287.     int i;
  288.  
  289.     // The app allows you to specify up to two major/minor type pairs
  290.     FillMajorTypes(m_ListInputMajor);
  291.     FillMajorTypes(m_ListInputMajor2);
  292.     FillMajorTypes(m_ListOutputMajor);
  293.     FillMajorTypes(m_ListOutputMajor2);
  294.  
  295.     // Initialize subtype list boxes
  296.     m_ListInputMinor.ResetContent();
  297.     m_ListInputMinor2.ResetContent();
  298.     m_ListOutputMinor.ResetContent();
  299.     m_ListOutputMinor2.ResetContent();
  300.  
  301.     // Set checkboxes to preferred default values
  302.     m_bAtLeastOneInputPin.SetCheck(1);
  303.     m_bAtLeastOneOutputPin.SetCheck(1);
  304.  
  305.     // Initialize merit box
  306.     m_ComboMerit.ResetContent();
  307.     for (i=0; i < NUM_MERIT_TYPES; i++)
  308.     {
  309.         m_ComboMerit.InsertString(i, merittypes[i].szName);
  310.         m_ComboMerit.SetItemData(i, merittypes[i].dwMerit);
  311.     }
  312.     m_ComboMerit.SetCurSel(4);  // "Normal" merit
  313.     
  314.     // Initialize pin categories
  315.     m_ComboInputCat.ResetContent();
  316.     m_ComboOutputCat.ResetContent();
  317.     m_ComboInputCat.AddString(TEXT("<Don't care>\0"));
  318.     m_ComboOutputCat.AddString(TEXT("<Don't care>\0"));
  319.  
  320.     // Fill pin category lists
  321.     for (i=1; i < NUM_PIN_TYPES; i++)
  322.     {
  323.         m_ComboInputCat.InsertString(i, pintypes[i].szName);
  324.         m_ComboInputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID);
  325.         m_ComboOutputCat.InsertString(i, pintypes[i].szName);
  326.         m_ComboOutputCat.SetItemDataPtr(i, (void *) pintypes[i].pGUID);
  327.     }
  328.     m_ComboInputCat.SetCurSel(0);
  329.     m_ComboOutputCat.SetCurSel(0);  
  330.     
  331.     // Clear filter list
  332.     m_ListFilters.ResetContent();  
  333.     m_StrNumFilters.SetWindowText(TEXT("Filters Matching Query : 0"));
  334.  
  335.     // Select the first item in each type list
  336.     FillSubType(m_ListInputMajor, m_ListInputMinor);
  337.     FillSubType(m_ListInputMajor2, m_ListInputMinor2);
  338.     FillSubType(m_ListOutputMajor, m_ListOutputMinor);
  339.     FillSubType(m_ListOutputMajor2, m_ListOutputMinor2);
  340.  
  341.     // Disable the second type/subtype listboxes until the user selects
  342.     // something other than "don't care" for the first type/subtype pair.
  343.     OnSelchangeListInputMajor();
  344.     OnSelchangeListOutputMajor();
  345. }
  346.  
  347. void CMapperDlg::OnButtonClear() 
  348. {
  349.     // Clear all values and reset dialog
  350.     SetDefaults();    
  351. }
  352.  
  353. void CMapperDlg::OnClose() 
  354. {
  355.     // Disable and destroy the tooltip control
  356.     if (m_pToolTip)
  357.     {
  358.         m_pToolTip->Activate(FALSE);
  359.         delete m_pToolTip;
  360.         m_pToolTip = 0;
  361.     }
  362.  
  363.     // Release FilterMapper interface
  364.     SAFE_RELEASE(m_pMapper);
  365.  
  366.     // Release COM
  367.     CoUninitialize();
  368.     
  369.     CDialog::OnClose();
  370. }
  371.  
  372. void CMapperDlg::OnDestroy()
  373. {
  374.     // Disable and destroy the tooltip control
  375.     if (m_pToolTip)
  376.     {
  377.         delete m_pToolTip;
  378.         m_pToolTip = 0;
  379.     }
  380.  
  381.     // Release FilterMapper interface
  382.     SAFE_RELEASE(m_pMapper);
  383.  
  384.     CDialog::OnDestroy();
  385. }
  386.  
  387. void CMapperDlg::FillMajorTypes(CListBox& m_List)
  388. {
  389.     m_List.ResetContent();
  390.  
  391.     // Fill the specified list box with major type name/GUID
  392.     for (int i=0; i < NUM_MAJOR_TYPES; i++)
  393.     {
  394.         m_List.InsertString(i, majortypes[i].szName);
  395.         m_List.SetItemDataPtr(i, (void *) majortypes[i].pGUID);
  396.     }
  397.  
  398.     m_List.SetCurSel(0);
  399. }
  400.  
  401. void CMapperDlg::FillSubType(CListBox& m_List, CListBox& m_ListMinor)
  402. {
  403.     const GUIDINFO *pSubtype;
  404.     int nSelection = m_List.GetCurSel();
  405.     int nMajorType;
  406.  
  407.     // First clear the subtype list
  408.     m_ListMinor.ResetContent();
  409.  
  410.     // If the "don't care" item was selected, clear and exit
  411.     if (nSelection == 0)
  412.     {
  413.         m_ListMinor.AddString(TEXT("<No subtypes>\0"));
  414.         m_ListMinor.SetCurSel(0);
  415.         return;
  416.     }
  417.     else
  418.         nMajorType = nSelection - 1;
  419.  
  420.     // Determine how to fill the minor type list, based on the
  421.     // currently selected major type.
  422.     pSubtype = pSubTypes[nMajorType];
  423.  
  424.     // If there's no associated subtype, just add a default
  425.     if (!pSubtype)
  426.     {
  427.         m_ListMinor.AddString(TEXT("<No subtypes>\0"));
  428.         m_ListMinor.SetCurSel(0);
  429.         return;
  430.     }
  431.     else
  432.     {
  433.         // Set a default item for "don't care"
  434.         m_ListMinor.AddString(TEXT("<Don't care>\0"));
  435.  
  436.         int i=0;
  437.  
  438.         // Fill the subtype list box.  Enter N item data to the N+1 list slot.
  439.         while (pSubtype[i].pGUID != NULL)
  440.         {
  441.             m_ListMinor.AddString(pSubtype[i].szName);
  442.             m_ListMinor.SetItemDataPtr(i+1, (void *) pSubtype[i].pGUID);
  443.             i++;
  444.         }
  445.  
  446.         m_ListMinor.SetCurSel(0);
  447.     }
  448. }
  449.  
  450. void CMapperDlg::OnSelchangeListInputMajor() 
  451. {
  452.     // User has selected a new major type, so refill the subtype list box
  453.     FillSubType(m_ListInputMajor, m_ListInputMinor);
  454.  
  455.     // Since the second type/subtype pair is irrelevant if the first
  456.     // is a don't care, disable the second set if appropriate.
  457.     EnableSecondTypePair(m_ListInputMajor, m_ListInputMajor2, m_ListInputMinor2);
  458. }
  459.  
  460. void CMapperDlg::OnSelchangeListInputMajor2() 
  461. {
  462.     // User has selected a new major type, so refill the subtype list box
  463.     FillSubType(m_ListInputMajor2, m_ListInputMinor2);
  464. }
  465.  
  466. void CMapperDlg::OnSelchangeListOutputMajor() 
  467. {
  468.     // User has selected a new major type, so refill the subtype list box
  469.     FillSubType(m_ListOutputMajor, m_ListOutputMinor);
  470.  
  471.     // Since the second type/subtype pair is irrelevant if the first
  472.     // is a don't care, disable the second set if appropriate.
  473.     EnableSecondTypePair(m_ListOutputMajor, m_ListOutputMajor2, m_ListOutputMinor2);
  474. }
  475.  
  476. void CMapperDlg::OnSelchangeListOutputMajor2() 
  477. {
  478.     // User has selected a new major type, so refill the subtype list box
  479.     FillSubType(m_ListOutputMajor2, m_ListOutputMinor2);
  480. }
  481.  
  482. void CMapperDlg::EnableSecondTypePair(CListBox& m_ListMajor, 
  483.                  CListBox& m_ListMajor2, CListBox& m_ListMinor2)
  484. {
  485.     // If there is no selection in the first major type listbox,
  486.     // clear and disable the second major/minor type listboxes.
  487.     if (m_ListMajor.GetCurSel() == 0)
  488.     {
  489.         m_ListMajor2.SetCurSel(0);
  490.         FillSubType(m_ListMajor2, m_ListMinor2);
  491.  
  492.         m_ListMajor2.EnableWindow(FALSE);
  493.         m_ListMinor2.EnableWindow(FALSE);
  494.     }
  495.     else
  496.     {
  497.         m_ListMajor2.EnableWindow(TRUE);
  498.         m_ListMinor2.EnableWindow(TRUE);
  499.     }
  500. }
  501.  
  502. void FillTypeArray(CListBox& m_ListMajor, CListBox& m_ListMinor,
  503.                    GUID *atypes, int nIndex, DWORD *pdwPairs)
  504. {
  505.     int nMajorSel = m_ListMajor.GetCurSel();
  506.     int nMinorSel = m_ListMinor.GetCurSel();
  507.  
  508.     // If no selection ("don't care"), just exit without modifying the array
  509.     if (nMajorSel <= 0)
  510.         return;
  511.  
  512.     // Get GUID for major type
  513.     const GUID *p1 = (const GUID *)m_ListMajor.GetItemDataPtr(nMajorSel);
  514.  
  515.     // Since the FilterMapper interface requires GUIDs (instead of GUID *),
  516.     // copy the specified GUID data into its array slot.
  517.     memcpy(&atypes[nIndex], p1, sizeof(GUID));
  518.  
  519.     // Increment number of type/subtype pairs
  520.     (*pdwPairs)++;
  521.  
  522.     // If no selection ("don't care"), or uninitialized (returning -1),
  523.     // just exit without modifying the array
  524.     if (nMinorSel <= 0)
  525.         return;
  526.     
  527.     // Get GUID for subtype
  528.     const GUID *p2 = (const GUID *)m_ListMinor.GetItemDataPtr(nMinorSel);
  529.  
  530.     if (p2)
  531.         memcpy(&atypes[nIndex+1], p2, sizeof(GUID));
  532. }
  533.  
  534. IEnumMoniker *CMapperDlg::GetFilterEnumerator(void)
  535. {
  536.     // First set up the boolean values
  537.     BOOL bExactMatch = m_bExactMatch.GetCheck();
  538.     BOOL bAtLeastOneInputPin = m_bAtLeastOneInputPin.GetCheck();
  539.     BOOL bAtLeastOneOutputPin = m_bAtLeastOneOutputPin.GetCheck();
  540.     BOOL bIsRenderer = m_bIsRenderer.GetCheck();
  541.  
  542.     // Merit
  543.     DWORD dwMerit = (DWORD) m_ComboMerit.GetItemData(m_ComboMerit.GetCurSel());
  544.  
  545.     // Pin categories
  546.     const GUID *pInCat  = (const GUID *)
  547.         m_ComboInputCat.GetItemDataPtr(m_ComboInputCat.GetCurSel());
  548.     const GUID *pOutCat = (const GUID *)
  549.         m_ComboOutputCat.GetItemDataPtr(m_ComboOutputCat.GetCurSel());
  550.  
  551.     // Major type/subtype pairs
  552.     DWORD dwInputTypes=0, dwOutputTypes=0;
  553.     GUID arrayInput[4], arrayOutput[4];
  554.  
  555.     // Initialize GUID type/subtype arrays
  556.     for (int i=0; i<4; i++)
  557.     {
  558.         arrayInput[i]  = GUID_NULL;
  559.         arrayOutput[i] = GUID_NULL;
  560.     }
  561.  
  562.     // Fill each of the four GUID arrays (input/output, major/minor).
  563.     // If the first call doesn't set anything (primary), don't bother to
  564.     // read the secondary value, since it would be invalid anyway due to
  565.     // its position within the array (2) but with a count of only 1.
  566.     FillTypeArray(m_ListInputMajor, m_ListInputMinor, arrayInput, 0, &dwInputTypes);
  567.     if (dwInputTypes)
  568.         FillTypeArray(m_ListInputMajor2, m_ListInputMinor2, arrayInput, 2, &dwInputTypes);
  569.  
  570.     FillTypeArray(m_ListOutputMajor, m_ListOutputMinor, arrayOutput, 0, &dwOutputTypes);
  571.     if (dwOutputTypes)
  572.         FillTypeArray(m_ListOutputMajor2, m_ListOutputMinor2, arrayOutput, 2, &dwOutputTypes);
  573.  
  574.     // Enumerate all filters that match the specified criteria
  575.     IEnumMoniker *pEnum;
  576.     HRESULT hr=S_OK;
  577.  
  578.     hr = m_pMapper->EnumMatchingFilters(
  579.             &pEnum,
  580.             0,                  // Reserved
  581.             bExactMatch,        // Use exact match?
  582.             dwMerit,            // Minimum merit
  583.             bAtLeastOneInputPin,
  584.             dwInputTypes,       // Number of major type/subtype pairs for input
  585.             arrayInput,         // Array of major type/subtype pairs for input
  586.             NULL,               // Input medium
  587.             pInCat,             // Input pin category
  588.             bIsRenderer,        // Must be a renderer?
  589.             bAtLeastOneOutputPin,
  590.             dwOutputTypes,      // Number of major type/subtype pairs for output
  591.             arrayOutput,        // Array of major type/subtype pairs for output
  592.             NULL,               // Output medium
  593.             pOutCat);           // Output pin category
  594.  
  595.     if (FAILED(hr))
  596.         return 0;
  597.     else
  598.         return pEnum;
  599. }
  600.  
  601. int CMapperDlg::GetFilenameByCLSID(REFCLSID clsid, TCHAR *szFile)
  602. {
  603.     HRESULT hr;
  604.     LPOLESTR strCLSID;
  605.     int rc=0;
  606.  
  607.     // Convert binary CLSID to a readable version
  608.     hr = StringFromCLSID(clsid, &strCLSID);
  609.     if(SUCCEEDED(hr))
  610.     {
  611.         TCHAR szKey[512];
  612.         CString strQuery(strCLSID);
  613.  
  614.         // Create key name for reading filename from registry
  615.         wsprintf(szKey, TEXT("Software\\Classes\\CLSID\\%s\\InprocServer32\0"),
  616.                  strQuery);
  617.  
  618.         // Free memory associated with strCLSID (allocated in StringFromCLSID)
  619.         CoTaskMemFree(strCLSID);
  620.  
  621.         HKEY hkeyFilter=0;
  622.         DWORD dwSize=MAX_PATH;
  623.         BYTE szFilename[MAX_PATH];
  624.  
  625.         // Open the CLSID key that contains information about the filter
  626.         rc = RegOpenKey(HKEY_LOCAL_MACHINE, szKey, &hkeyFilter);
  627.         if (rc == ERROR_SUCCESS)
  628.         {
  629.             rc = RegQueryValueEx(hkeyFilter, NULL,  // Read (Default) value
  630.                                  NULL, NULL, szFilename, &dwSize);
  631.            
  632.             if (rc == ERROR_SUCCESS)
  633.                 wsprintf(szFile, TEXT("%s"), szFilename);
  634.  
  635.             RegCloseKey(hkeyFilter);
  636.         }
  637.     }
  638.     else
  639.         return -1;
  640.  
  641.     return rc;
  642. }
  643.  
  644. // Read merit and version information
  645. HRESULT CMapperDlg::GetMerit(IPropertyBag *pPropBag, DWORD *pdwMerit)
  646. {
  647.     HRESULT hr;
  648.     IAMFilterData *pData=0;
  649.  
  650.     *pdwMerit = 0;
  651.  
  652.     VARIANT varFilData={0};
  653.     varFilData.vt = VT_UI1 | VT_ARRAY;
  654.     varFilData.parray = 0;     // docs say to zero this
  655.  
  656.     BYTE *pbFilterData = 0;    // 0 if not read
  657.     DWORD dwcbFilterDAta = 0;  // 0 if not read
  658.  
  659.     // Read compressed filter data from the property bag with a variant
  660.     hr = pPropBag->Read(L"FilterData", &varFilData, 0);
  661.     if(SUCCEEDED(hr))
  662.     {
  663.         ASSERT(varFilData.vt == (VT_UI1 | VT_ARRAY));
  664.         dwcbFilterDAta = varFilData.parray->rgsabound[0].cElements;
  665.  
  666.         // Access the filter data
  667.         HRESULT hrTmp = SafeArrayAccessData(varFilData.parray, (void **)&pbFilterData);
  668.         ASSERT(hrTmp == S_OK);
  669.         ASSERT(pbFilterData);
  670.     }
  671.     else
  672.     {
  673.         ASSERT(dwcbFilterDAta == 0 && pbFilterData == 0);
  674.         return E_FAIL;
  675.     }
  676.  
  677.     // Get the IAMFilterData interface for parsing the filter data
  678.     hr = m_pMapper->QueryInterface(IID_IAMFilterData, (void **)&pData);
  679.  
  680.     if(SUCCEEDED(hr))
  681.     {
  682.         BYTE *pb=0;
  683.  
  684.         // Use a helper method to parse the binary filter data.  Pass in
  685.         // the pointer to the filter data, its size, and a buffer to fill with
  686.         // the resulting data.  The "pb" buffer is allocated with CoTaskMemAlloc,
  687.         // so it must be correspondingly freed by the caller.
  688.         hr = pData->ParseFilterData(pbFilterData, dwcbFilterDAta, &pb);
  689.         if(SUCCEEDED(hr))
  690.         {
  691.             REGFILTER2 *pFil = ((REGFILTER2 **)pb)[0];
  692.  
  693.             if(pbFilterData)
  694.             {
  695.                 HRESULT hrTmp = SafeArrayUnaccessData(varFilData.parray);
  696.                 ASSERT(hrTmp == S_OK);
  697.  
  698.                 hrTmp = VariantClear(&varFilData);
  699.                 ASSERT(hrTmp == S_OK);
  700.             }
  701.  
  702.             // Assign the merit value from the REGFILTER2 structure
  703.             if (pFil)
  704.                 *pdwMerit = pFil->dwMerit;
  705.  
  706.             // Free the memory allocated by ParseFilterData
  707.             if (pb)
  708.                 CoTaskMemFree(pb);
  709.         }
  710.  
  711.         // Release the IAMFilterData interface
  712.         pData->Release();
  713.     }
  714.  
  715.     return hr;
  716. }
  717.  
  718. void CMapperDlg::AddMerit(TCHAR *szInfo, DWORD dwMerit)
  719. {
  720.     TCHAR szMerit[32];
  721.  
  722.     switch (dwMerit)
  723.     {
  724.         case MERIT_NORMAL:
  725.              wsprintf(szMerit, TEXT("MERIT_NORMAL\0"));
  726.              break;     // Assume normal
  727.         case MERIT_PREFERRED:
  728.              wsprintf(szMerit, TEXT("MERIT_PREFERRED\0"));
  729.              break;
  730.         case MERIT_UNLIKELY:
  731.              wsprintf(szMerit, TEXT("MERIT_UNLIKELY\0"));
  732.              break;
  733.         case MERIT_DO_NOT_USE:
  734.              wsprintf(szMerit, TEXT("MERIT_DO_NOT_USE\0"));
  735.              break;
  736.         case MERIT_SW_COMPRESSOR:
  737.              wsprintf(szMerit, TEXT("MERIT_SW_COMPRESSOR\0"));
  738.              break;
  739.         case MERIT_HW_COMPRESSOR:
  740.              wsprintf(szMerit, TEXT("MERIT_HW_COMPRESSOR\0"));
  741.              break;
  742.         
  743.         default:
  744.              wsprintf(szMerit, TEXT("0x%08x\0"), dwMerit);
  745.              break;
  746.     }
  747.  
  748.     // Add new merit information to string
  749.     _tcscat(szInfo, szMerit);
  750. }
  751.  
  752.  
  753. void CMapperDlg::AddFilter(const TCHAR *szFilterName, const GUID *pCatGuid, DWORD dwMerit)
  754. {
  755.     TCHAR szInfo[300], szFilename[255];
  756.  
  757.     // First add the friendly name of the filter
  758.     wsprintf(szInfo, TEXT("%s\t\0"), szFilterName);
  759.  
  760.     // Add the filter's merit value
  761.     AddMerit(szInfo, dwMerit);
  762.  
  763.     // Get the filter's server name from the registry
  764.     int rc = GetFilenameByCLSID(*pCatGuid, szFilename);
  765.  
  766.     // Add the filter's server name
  767.     if (rc == ERROR_SUCCESS)
  768.     {
  769.         _tcscat(szInfo, TEXT("\t\0"));
  770.         _tcscat(szInfo, szFilename);
  771.     }
  772.  
  773.     // Add the filter name and filename to the listbox
  774.     m_ListFilters.AddString(szInfo);
  775. }
  776.  
  777. void CMapperDlg::OnButtonSearch() 
  778. {
  779.     HRESULT hr=S_OK;
  780.     IEnumMoniker *pEnum;
  781.     IMoniker *pMoniker=0;
  782.     ULONG cFetched=0;
  783.     VARIANT varName={0};
  784.     int nFilters=0;    
  785.  
  786.     // Clear any previous results
  787.     m_ListFilters.ResetContent();
  788.  
  789.     // Enumerate filters based on the current dialog box selections
  790.     pEnum = GetFilterEnumerator();
  791.     if (!pEnum)
  792.     {
  793.         m_ListFilters.AddString(TEXT("<No filters matched query>"));
  794.         return;
  795.     }
  796.     hr = pEnum->Reset();
  797.  
  798.     // Enumerate all filters that match the search criteria.  The enumerator
  799.     // that is returned from GetFilterEnumerator() will only list filters
  800.     // that matched the user's search request.
  801.     while((hr = pEnum->Next(1, &pMoniker, &cFetched)) == S_OK)
  802.     {
  803.         IPropertyBag *pPropBag;
  804.         ASSERT(pMoniker);
  805.  
  806.         // Associate the moniker with a file
  807.         hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
  808.                                     (void **)&pPropBag);
  809.         ASSERT(SUCCEEDED(hr));
  810.         ASSERT(pPropBag);
  811.         if (FAILED(hr))
  812.             continue;
  813.  
  814.         // Read filter name from property bag
  815.         varName.vt = VT_BSTR;
  816.         hr = pPropBag->Read(L"FriendlyName", &varName, 0);
  817.         if (FAILED(hr))
  818.             continue;
  819.  
  820.         // Get filter name (converting BSTR name to a CString)
  821.         CString str(varName.bstrVal);
  822.         SysFreeString(varName.bstrVal);
  823.         nFilters++;
  824.         
  825.         // Read Merit value from property bag
  826.         DWORD dwMerit;
  827.         GetMerit(pPropBag, &dwMerit);
  828.  
  829.         // Read filter's CLSID from property bag.  This CLSID string will be
  830.         // converted to a binary CLSID and passed to AddFilter(), which will
  831.         // add the filter's name to the listbox and its CLSID to the listbox
  832.         // item's DataPtr item.
  833.         VARIANT varFilterClsid;
  834.         varFilterClsid.vt = VT_BSTR;
  835.  
  836.         // Read CLSID string from property bag
  837.         hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0);
  838.         if(SUCCEEDED(hr))
  839.         {
  840.             CLSID clsidFilter;
  841.  
  842.             // Add filter name and filename to listbox
  843.             if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK)
  844.             {
  845.                 AddFilter(str, &clsidFilter, dwMerit);
  846.             }
  847.  
  848.             SysFreeString(varFilterClsid.bstrVal);
  849.         }
  850.  
  851.         // Clean up interfaces
  852.         SAFE_RELEASE(pPropBag);
  853.         SAFE_RELEASE(pMoniker);
  854.     }   
  855.  
  856.     // Display number of filters matching query
  857.     TCHAR szNumFilters[48];
  858.     wsprintf(szNumFilters, TEXT("Filters Matching Query : %d"), nFilters);
  859.     m_StrNumFilters.SetWindowText(szNumFilters);
  860.  
  861.     // Clean up enumerator
  862.     if (pEnum)
  863.         pEnum->Release();
  864. }
  865.  
  866.  
  867.  
  868.